package org.cleverframe.modules.sys.service;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.cleverframe.common.service.BaseService;
import org.cleverframe.common.vo.AjaxMessage;
import org.cleverframe.modules.sys.SysBeanNames;
import org.cleverframe.modules.sys.dao.DictDao;
import org.cleverframe.modules.sys.dao.MenuDao;
import org.cleverframe.modules.sys.entity.Dict;
import org.cleverframe.modules.sys.entity.MDict;
import org.cleverframe.modules.sys.entity.Menu;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

/**
 * 系统菜单<dr>
 * 
 * @author LiZhiWei
 * @version 2015年6月4日 下午9:34:50
 */
@Service(SysBeanNames.MenuService)
public class MenuService extends BaseService
{
    /** 字典类型名称，用于获取系统模块菜单的可选值 */
    public final static String SYSTEM_MODULE_MENU_CATEGORY = "系统模块菜单类别";

    @Autowired
    @Qualifier(SysBeanNames.MenuDao)
    private MenuDao menuDao;

    @Autowired
    @Qualifier(SysBeanNames.DictDao)
    private DictDao dictDao;

    /**
     * 返回所有系统菜单
     */
    public List<Menu> getAllMenu()
    {
        return this.menuDao.getAllMenu();
    }


    /**
     * 查询系统菜单<br>
     * @param category 类别
     * @param menuType
     * @param name
     * @param id
     * @param uuid
     * @return 
     */
    public List<Menu> findMenu(String category, String menuType, String name, Long id, String uuid)
    {
        return this.menuDao.findMenu(category, menuType, name, id, uuid);
    }

    /**
     * 获取所有菜单信息，排除当前菜单以及当前菜单的所有下级菜单<br>
     * @param fullPath 当前菜单全路径
     */
    public List<Menu> getMenuTreeExcludeOneself(String fullPath)
    {
        return menuDao.getMenuTreeExcludeOneself(fullPath);
    }

    /**
     * 获取特定类别的菜单<br>
     * @param category 菜单类别
     */
    public List<Menu> findMenuByCategory(String category)
    {
        return menuDao.findMenuByCategory(category);
    }

    /**
     * 保存菜单对象<br>
     * 菜单类别：所有同一类别的菜单应该是一颗完整的菜单树<br>
     * 菜单类型：所有菜单菜单类别是系统模块名的菜单都是系统模块菜单,菜单类别是根据login_name来命名的都是个人快捷菜单<br>
     * 同一棵树上的菜单，菜单类别、菜单类型都应该一致<br>
     */
    public boolean addMenu(Menu menu, AjaxMessage message)
    {
        /* ----------------------------------保存菜单验证---------------------------------- */
        Menu parentMenu = null;
        if (menu.isRootMenu())
        {
            if (Menu.MENU_TYPE_SYSTEM.equals(menu.getMenuType()))
            {
                // 系统菜单可选值验证
                boolean flag = false;
                List<Dict> dictList = dictDao.findDictByType(SYSTEM_MODULE_MENU_CATEGORY);
                for (Dict dict : dictList)
                {
                    if (dict.getDictValue().equals(menu.getCategory()))
                    {
                        flag = true;
                        break;
                    }
                }
                if (false == flag)
                {
                    message.setMessage("保存的菜单类型是“系统模块菜单”，但其菜单类别值在“系统模块菜单类别”中未找到");
                    return false;
                }
            }
            else
            {
                // 个人快捷菜单，菜单类别取值
                String category = Menu.SHORTCUT_MENU_PREFIX + userUtils.getCurrentUserLoginName();
                if (StringUtils.isBlank(menu.getCategory()))
                {
                    menu.setCategory(category);
                }
                else
                {
                    if (!category.equals(menu.getCategory()))
                    {
                        message.setMessage("保存的菜单类型是“个人快捷菜单”，但个人快捷菜单的菜单类别值不满足规范");
                        return false;
                    }
                }
            }
        }
        else
        {
            parentMenu = menuDao.getHibernateDao().get(menu.getParentId());
            if (parentMenu == null)
            {
                message.setMessage("菜单的上级菜单不存在");
                return false;
            }
            // 同一棵树上的菜单，菜单类别、菜单类型都应该一致
            if (!parentMenu.getMenuType().equals(menu.getMenuType()) || !parentMenu.getCategory().equals(menu.getCategory()))
            {
                message.setMessage("当前菜单的“菜单类别、菜单类型”必须要与父菜单一致");
                return false;
            }
        }
        /* ----------------------------------保存菜单---------------------------------- */
        if (menu.isRootMenu())
        {
            menu.setParentId(-1L);
        }
        menuDao.getHibernateDao().save(menu);

        // 设置FullPath，Hibernate自动更新
        if (menu.isRootMenu())
        {
            menu.setFullPath(menu.getId().toString());
        }
        else
        {
            menu.setFullPath(parentMenu.getFullPath() + Menu.FULL_PATH_SPLIT + menu.getId());
        }
        return true;
    }

    /**
     * 更新菜单对象<br>
     * 修改菜单：不能修改（full_path、category、menu_type）<br>
     */
    public boolean updateMenu(Menu menu, AjaxMessage message)
    {
        Menu oldMenu = menuDao.getHibernateDao().get(menu.getId());
        /* ----------------------------------验证菜单更新---------------------------------- */
        if (oldMenu == null)
        {
            message.setMessage("菜[" + menu.getName() + "]不存在");
            return false;
        }
        Menu parentMenu = null;
        if (!menu.isRootMenu())
        {
            parentMenu = menuDao.getHibernateDao().get(menu.getParentId());
            if (parentMenu == null)
            {
                message.setMessage("菜单的上级菜单不存在");
                return false;
            }
        }
        if (oldMenu.getParentId().equals(menu.getParentId()))
        {
            // 没有修改父级编号-节点位置不变
            if (!menu.isRootMenu())
            {
                // 修改的节点不是根节点
                if (!oldMenu.getCategory().equals(menu.getCategory()))
                {
                    message.setMessage("当前菜单的“菜单类别”必须要与父菜单一致");
                    return false;
                }
                if (!oldMenu.getMenuType().equals(menu.getMenuType()))
                {
                    message.setMessage("当前菜单的“菜单类型”必须要与父菜单一致");
                    return false;
                }
            }
        }
        else
        {
            // 修改了父级编号-节点位置发生变化
            if (!menu.isRootMenu())
            {
                // 修改的节点不是根节点
                if (!parentMenu.getCategory().equals(menu.getCategory()))
                {
                    message.setMessage("当前菜单的“菜单类别”必须要与父菜单一致");
                    return false;
                }
                if (!parentMenu.getMenuType().equals(menu.getMenuType()))
                {
                    message.setMessage("当前菜单的“菜单类型”必须要与父菜单一致");
                    return false;
                }
            }
        }
        /* ----------------------------------更新菜单---------------------------------- */
        int updateCategoryAndTypeCount = -1;
        if (!oldMenu.getCategory().equals(menu.getCategory()) || !oldMenu.getMenuType().equals(menu.getMenuType()))
        {
            // 修改了category、menu_type
            String fullPath = oldMenu.getFullPath() + "%";
            String category = menu.getCategory();
            char menuType = menu.getMenuType();
            updateCategoryAndTypeCount = menuDao.updateMenuCategoryAndType(fullPath, category, menuType);
        }
        
        int updateFullPathCount = -1;
        if (!oldMenu.getParentId().equals(menu.getParentId()))
        {
            // 修改了父级编号-节点位置发生变化，需要更新FullPath属性
            String fullPath = oldMenu.getFullPath() + "%";
            String parentFullPath = "";
            if (parentMenu != null)
            {
                parentFullPath = parentMenu.getFullPath();
            }
            int fullPathSubstringBegin = oldMenu.getFullPath().lastIndexOf(MDict.FULL_PATH_SPLIT) + 1;
            if (fullPathSubstringBegin <= 0)
            {
                fullPathSubstringBegin = 1;
            }
            String fullPathSubstring = oldMenu.getFullPath().substring(fullPathSubstringBegin - 1);
            if (!parentFullPath.endsWith(Menu.FULL_PATH_SPLIT + "") && !fullPathSubstring.startsWith(Menu.FULL_PATH_SPLIT + ""))
            {
                // "...-xxx" + "xxx-..."
                parentFullPath = parentFullPath + Menu.FULL_PATH_SPLIT;
            }
            if (parentFullPath.endsWith(Menu.FULL_PATH_SPLIT + "") && fullPathSubstring.startsWith(Menu.FULL_PATH_SPLIT + ""))
            {
                // "...-xxx-" + "-xxx-..."
                parentFullPath = parentFullPath.substring(0, parentFullPath.length() - 1);
            }
            if (StringUtils.isBlank(parentFullPath) && fullPathSubstring.startsWith(Menu.FULL_PATH_SPLIT + ""))
            {
                // "" + "-xxx-..."
                fullPathSubstringBegin = fullPathSubstringBegin + 1;
            }
            updateFullPathCount = menuDao.updateFullPath(fullPath, parentFullPath, fullPathSubstringBegin);
        }

        if (updateFullPathCount >= 0 && updateCategoryAndTypeCount >= 0)
        {
            // 既更新了FullPath又更新了category、menu_type，需要保证修改的数量相同
            if (updateFullPathCount != updateCategoryAndTypeCount)
            {
                throw new RuntimeException("更新菜单出错！在更新期间可能出现其他人修改，请重试！");
            }
        }

        // 重新计算full_path、category、menu_type、parent_id
        if (menu.isRootMenu())
        {
            menu.setParentId(-1L);
            menu.setFullPath(menu.getId().toString());
        }
        else
        {
            menu.setCategory(parentMenu.getCategory());
            menu.setMenuType(parentMenu.getMenuType());
            menu.setFullPath(parentMenu.getFullPath() + Menu.FULL_PATH_SPLIT + menu.getId());
        }
        menuDao.getHibernateDao().getSession().evict(oldMenu);
        menuDao.getHibernateDao().update(menu);
        return true;
    }

    /**
     * 删除菜单对象<br>
     */
    public int deleteMenu(String fullPath)
    {
        return menuDao.deleteMenu(fullPath);
    }
    
    /**
     * 获取角色拥有的菜单<br>
     * @param roleId 角色ID
     * @return 菜单集合
     */
    public List<Menu> findMenuByRoleId(Long roleId)
    {
        return menuDao.findMenuByRoleId(roleId);
    }
    
    /**
     * 获取用户拥有的所有菜单<br>
     * @param userId 用户ID
     * @return 菜单集合
     */
    public List<Menu> findMenuByUserId(Long userId)
    {
        return menuDao.findMenuByUserId(userId);
    }
    
    /**
     * 获取用户拥有的菜单，根据菜单类别过滤<br>
     * @param userId 用户ID
     * @param category 菜单类别
     * @return 菜单集合
     */
    public List<Menu> findMenuByUserIdAndCategory(Long userId, String category)
    {
        return menuDao.findMenuByUserIdAndCategory(userId, category);
    }
}
